<?php
/**
 * Created by PhpStorm.
 * User: lenovo
 * Date: 2020/5/20
 * Time: 15:33
 */

namespace App\HttpController\V1;


use App\Logic\AppLogic;
use App\Logic\Tool;
use App\Services\HelpService;
use EasySwoole\Http\Response;
use EasySwoole\Http\Message\Status;
use EasySwoole\Http\AbstractInterface\Controller;
use EasySwoole\Jwt\Jwt;

abstract class ApiController extends Controller
{
       public   $param = array();
       public   $app = array();

    /**
     * showdoc
     * @catalog 开放平台
     * @title  对接加密说明
     * @description 上传数据，下发数据，都是固定以下四个参数(上行多一个access_key)：timestamp，nonce,content,sign，timestamp是时间戳，nonce是随机字符串，要求是6位，提交时候nonce使用aes加密。content是请求参数密文，获取方式如下：表单数据，json_encode，然后aes加密。$sign是签名，生成规则如下：$content.$timestamp.$nonce，然后再md5,注意，这边的nonce是明文的。
     * @method
     * @url
     * @param  accesskey 是 string 应用access_key
     * @param  nonce  是 string 消息随机字符串，由时间戳+6位随机字符串，用于消息校验,提交之前请加密
     * @param  content  是 string 除了access_key,timestamp，nonce,content,sign这是5参数，其他参数都是包裹在content，并进行aes加密
     * @param  timestamp  是 string 时间戳
     * @param  sign  是 string 签名，生成规则$content.$timestamp.$nonce，注意，这时候的nonce没有加密
     * @remark 下发的数据也是加密的，请不要再客户端请求，否则秘钥可能泄露。
     */

    protected function onRequest(?string $action): ?bool
    {
        $content = $this->request()->getRequestParam('content');
        $timestamp = $this->request()->getRequestParam('timestamp');
        $nonce = $this->request()->getRequestParam('nonce');
        $sign = $this->request()->getRequestParam('sign');
        $access_key = $this->request()->getRequestParam('access_key');
        $appLogic = new AppLogic();
        $app = $appLogic->findByAccessKey($access_key);

        if(empty($app)){
            $this->writeJson(Status::CODE_BAD_REQUEST,  array(),'Bad Request');
            return false;
        }

        $nonce = HelpService::aesDecrypt($nonce,$app['access_key'],$app['secret_key']);

        if(!$this->checkSign($content,$timestamp, $nonce,$sign)){
            $this->writeJson(Status::CODE_UNAUTHORIZED,  HelpService::aesEncrypt(json_encode(array()),$app['access_key'],$app['secret_key']),'Bad Request');
             return false;
        }

        $this->param =  json_decode(preg_replace('/[\x00-\x1F]/','', HelpService::aesDecrypt($content,$app['access_key'],$app['secret_key'])),true);
        $this->param['_rand_num'] = time();#设置个默认表单，防止验证器报空错
        $this->param['access_key'] = $app['access_key'];
        $this->param['secret_key'] = $app['secret_key'];
        $this->param['app_id'] = $app['id'];

         $this->app  = $app;
     return true;
    }

    /**
     * 检测签名
     */
    private function checkSign($content,$timestamp, $nonce,$sign){
       if(md5($content.$timestamp.$nonce)==$sign){
           return true;
       }
       return false;
    }

    protected function writeJson($statusCode = 200, $result = null, $msg = null)
    {
        if (!$this->response()->isEndResponse()) {
            $data = Array(
                "code" => $statusCode,
                "msg" => $msg,
                "result" => $result,
            );

            $this->response()->write(json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
            $this->response()->withHeader('Content-type', 'application/json;charset=utf-8');
            $this->response()->withStatus($statusCode);
            return true;
        } else {
            return false;
        }
    }
}